import 'dart:io';
import 'dart:convert'; // 需要用到 utf8 和 LineSplitter

// --- 文件和目录操作示例 ---

Future<void> fileAndDirectoryExamples() async {
  print('\n--- 开始文件和目录操作示例 ---');

  // --- 准备工作：创建示例文件和目录 ---
  final tempDir = Directory('temp_io_dir');
  final configFile = File('${tempDir.path}/config.txt');
  final logFile = File('${tempDir.path}/log.txt');
  final binaryFile = File('${tempDir.path}/binary_data.bin');
  final subDir = Directory('${tempDir.path}/subdir');

  try {
    // 清理可能存在的旧目录
    if (await tempDir.exists()) {
      print('删除旧的临时目录...');
      await tempDir.delete(recursive: true);
    }
    // 创建新目录和子目录
    print('创建临时目录: ${tempDir.path}');
    await tempDir.create(recursive: true);
    print('创建子目录: ${subDir.path}');
    await subDir.create();

    // 创建并写入初始 config.txt 内容
    print('创建并写入 config.txt...');
    await configFile.writeAsString(
      'line1=value1\nline2=value2\nline3=你好 Dart IO\n',
    );
    print('创建并写入空的 log.txt...');
    await logFile.create(); // 创建空文件
    print('创建并写入 binary_data.bin...');
    await binaryFile.writeAsBytes([0, 1, 2, 3, 255]); // 写入一些字节

    print('--- 准备工作完成 ---');

    // --- 1. 读取文件为文本 ---
    print('\n--- 读取文件为文本 (readAsString) ---');
    try {
      // 将整个文件读入单个字符串
      var stringContents = await configFile.readAsString();
      print('config.txt 内容 (readAsString):\n$stringContents');
      print('文件共有 ${stringContents.length} 个字符。');

      // 将文件的每一行放入各自的字符串中
      print('\n--- 读取文件为文本 (readAsLines) ---');
      var lines = await configFile.readAsLines();
      print('config.txt 内容 (readAsLines):');
      for (var line in lines) {
        print('  $line');
      }
      print('文件共有 ${lines.length} 行。');
    } catch (e) {
      print('读取文本文件时出错: $e');
    }

    // --- 2. 读取文件为二进制 ---
    print('\n--- 读取文件为二进制 (readAsBytes) ---');
    try {
      var contents = await binaryFile.readAsBytes();
      print('binary_data.bin 内容 (字节): $contents');
      print('文件共有 ${contents.length} 字节。');
    } catch (e) {
      print('读取二进制文件时出错: $e');
    }

    // --- 3. 流式读取文件内容 ---
    print('\n--- 流式读取文件内容 ---');
    Stream<List<int>> inputStream = configFile.openRead();
    var linesStream = utf8.decoder
        .bind(inputStream)
        .transform(const LineSplitter());
    try {
      print('通过流逐行读取 config.txt:');
      await for (final line in linesStream) {
        print('  从流中获取到 ${line.length} 个字符: "$line"');
      }
      print('文件流已关闭');
    } catch (e) {
      print('流式读取文件时出错: $e');
    }

    // --- 4. 写入文件内容 ---
    print('\n--- 写入文件内容 (覆盖模式) ---');
    IOSink sinkWrite;
    try {
      sinkWrite = logFile.openWrite(mode: FileMode.write); // 默认模式，覆盖
      sinkWrite.write('文件首次访问于 ${DateTime.now()}\n');
      sinkWrite.writeln('这是新写入的第一行。');
      sinkWrite.writeln('这是新写入的第二行。');
      await sinkWrite.flush(); // 确保写入磁盘
      await sinkWrite.close(); // 关闭 sink
      print('已覆盖写入 log.txt。内容:');
      print(await logFile.readAsString());
    } catch (e) {
      print('覆盖写入文件时出错: $e');
    }

    print('\n--- 写入文件内容 (追加模式) ---');
    IOSink sinkAppend;
    try {
      sinkAppend = logFile.openWrite(mode: FileMode.append); // 追加模式
      sinkAppend.write('文件追加访问于 ${DateTime.now()}\n');
      sinkAppend.writeln('这是追加的一行。');
      await sinkAppend.flush();
      await sinkAppend.close();
      print('已追加写入 log.txt。内容:');
      print(await logFile.readAsString());
    } catch (e) {
      print('追加写入文件时出错: $e');
    }

    // --- 5. 列出目录中的文件 ---
    print('\n--- 列出目录中的文件 (${tempDir.path}) ---');
    try {
      var dirListStream = tempDir.list(
        recursive: false,
      ); // recursive: false 只列出当前层级
      print('目录内容 (非递归):');
      await for (final FileSystemEntity f in dirListStream) {
        if (f is File) {
          print('  找到文件: ${f.path}');
        } else if (f is Directory) {
          print('  找到目录: ${f.path}');
        }
      }

      print('\n目录内容 (递归):');
      var dirListRecursiveStream = tempDir.list(recursive: true);
      await for (final FileSystemEntity f in dirListRecursiveStream) {
        if (f is File) {
          print('  找到文件: ${f.path}');
        } else if (f is Directory) {
          print('  找到目录: ${f.path}');
        }
      }
    } catch (e) {
      print('列出目录时出错: $e');
    }

    // --- 6. 其他常用功能示例 ---
    print('\n--- 其他常用功能 ---');
    // 获取文件长度
    try {
      print('config.txt 的长度: ${await configFile.length()} 字节');
    } catch (e) {
      print('获取文件长度时出错: $e');
    }
    // 重命名文件
    try {
      final renamedFile = await configFile.rename(
        '${tempDir.path}/renamed_config.txt',
      );
      print('config.txt 已重命名为: ${renamedFile.path}');
      assert(await renamedFile.exists());
      assert(!await configFile.exists()); // 原文件不再存在
      // 再改回来，方便后续清理
      await renamedFile.rename(configFile.path);
      print('已将文件改回: ${configFile.path}');
    } catch (e) {
      print('重命名文件时出错: $e');
    }
  } catch (e) {
    print('在文件/目录操作的主 try 块中捕获到错误: $e');
  } finally {
    // --- 清理工作：删除示例文件和目录 ---
    print('\n--- 开始清理工作 ---');
    try {
      if (await tempDir.exists()) {
        print('删除临时目录及其内容: ${tempDir.path}');
        await tempDir.delete(recursive: true);
        print('清理完成。');
      } else {
        print('临时目录不存在，无需清理。');
      }
    } catch (e) {
      print('清理临时目录时出错: $e');
    }
  }
  print('\n--- 文件和目录操作示例结束 ---');
}

// --- HTTP 服务器示例 ---

Future<void> httpServerExample() async {
  print('\n--- HTTP 服务器示例 ---');
  final String host = 'localhost'; // 或者 InternetAddress.loopbackIPv4.host
  final int port = 8888;

  try {
    // 绑定服务器到指定地址和端口
    final server = await HttpServer.bind(host, port);
    print('HTTP 服务器已启动，监听地址: http://$host:$port');
    print('你可以尝试访问:');
    print('  http://$host:$port/dart  (应该返回 "Hello from the server")');
    print('  http://$host:$port/other (应该返回 404 Not Found)');
    print('\n注意：服务器将持续运行，直到你手动停止脚本 (例如按 Ctrl+C)。');

    // 监听传入的请求
    await for (final HttpRequest request in server) {
      processRequest(request); // 处理每个请求
    }
  } catch (e) {
    print('启动或运行 HTTP 服务器时出错: $e');
    print('请检查端口 $port 是否已被占用。');
  }
}

// 处理 HTTP 请求的函数
void processRequest(HttpRequest request) {
  print('收到请求: ${request.method} ${request.uri.path}');
  final response = request.response;

  // 根据请求路径进行响应
  if (request.uri.path == '/dart') {
    response
      ..headers.contentType = ContentType(
        'text',
        'plain',
        charset: 'utf-8',
      ) // 设置内容类型和编码
      ..statusCode =
          HttpStatus
              .ok // 显式设置状态码 (默认是 200 OK)
      ..write('Hello from the Dart server! 你好，服务器！');
  } else if (request.uri.path == '/json') {
    response
      ..headers.contentType =
          ContentType
              .json // 使用预定义的 JSON 类型
      ..write(
        jsonEncode({
          'message': '这是一个 JSON 响应',
          'timestamp': DateTime.now().toIso8601String(),
        }),
      );
  } else {
    // 对于其他路径，返回 404
    response.statusCode = HttpStatus.notFound;
    response.write('404 - Not Found: "${request.uri.path}"');
  }

  // 关闭响应流，发送响应给客户端
  response.close();
}

// --- 主函数 ---
Future<void> main() async {
  print('--- Dart IO 示例程序开始 ---');

  // 运行文件和目录操作示例
  await fileAndDirectoryExamples();

  // 运行 HTTP 服务器示例 (放在最后，因为它会一直运行)
  // 如果你想先测试文件操作，可以注释掉下面这行
  await httpServerExample();

  // 由于 httpServerExample 会持续运行，下面的代码通常不会执行，除非服务器启动失败
  print('\n--- Dart IO 示例程序结束 (如果服务器未启动或出错) ---');
}
